package com.nekonomics
package persistence.query

import domain.detail.CartItemDetail

import cats.data.NonEmptyList
import doobie.*
import doobie.implicits.*
import doobie.postgres.implicits.*
import zio.*

trait CartItemDetailRepo {

  def listPageByUserId(userId: Long, pageNum: Int, pageSize: Int): ConnectionIO[List[CartItemDetail]]
  def countByUserId(userId: Long): ConnectionIO[Long]
  def listBy(userId: Long, skuIds: List[Long]): ConnectionIO[List[CartItemDetail]]
}

object CartItemDetailRepo {
  val live: ULayer[CartItemDetailRepo] = ZLayer.succeed(new CartItemDetailRepoLive)
}



class CartItemDetailRepoLive extends CartItemDetailRepo {


  private val sqlTemp =
    sql"""
         |select
         |  ci.id, spu.name,
         |  sku.id, spu.id,
         |  sku.price, ci.quantity, sku.image_url,
         |  ci.created_at, ci.updated_at
         |from public.cart_item ci
         |join public.sku sku on ci.sku_id = sku.id
         |join public.spu spu on sku.spu_id = spu.id
         |""".stripMargin


  override def listBy(userId: Long, skuIds: List[Long]): doobie.ConnectionIO[List[CartItemDetail]] = {
    val cond1 =
      sql"""
        |ci.user_id=$userId
        |and sku.is_active = true
        """.stripMargin
    val cond2 = Fragments.in(fr"sku.id", NonEmptyList.fromListUnsafe(skuIds))
    (sqlTemp ++ Fragments.whereAnd(cond1, cond2))
      .query[CartItemDetail]
      .to[List]
  }

  override def listPageByUserId(userId: Long, pageNum: Int, pageSize: Int): ConnectionIO[List[CartItemDetail]] = {
    (sqlTemp ++
      sql"""
        |where ci.user_id = $userId
        |and sku.is_active = true
        |limit $pageSize offset ${pageSize * (pageNum - 1)}
        """.stripMargin)
      .query[CartItemDetail]
      .to[List]
  }


  override def countByUserId(userId: Long): doobie.ConnectionIO[Long] = {
    sql"select count(id) from public.cart_item where user_id = $userId"
      .query[Long]
      .unique
  }
}
